#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2012-2024. All rights reserved

import os
import sys
import subprocess
import json
import json5
import re


class SystemCapability:

    def __init__(self, clear_devicetype):
        self.work_dir = os.path.dirname(os.path.realpath(__file__))
        self.code_root = self._get_config("code_root")
        self.xts_root = self._get_config("xts_root")
        self.exclude_project = self._get_config("exclude_project")
        self.dir_to_modules = self._get_config("dir_to_modules")
        self.subsystem_of_module = self._get_config("subsystem_of_module")
        # self.xts_root = os.path.join(self.code_root, 'test/xts/acts')
        self.components_syscaps = {}
        self._clear_devicetype = clear_devicetype

    def _get_config(self, key):
        with open('config.json', 'r') as rf:
            mydict = json.load(rf)
            return mydict.get(key)

    def prepare(self):
        cmd = "ls *.sh"
        ret = subprocess.run([cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        sh_list = ret.stdout.decode().strip().split('\n')
        print("sh_list={}".format(sh_list))

        chmod_cmd = "chmod +x {}".format(" ".join(sh_list))
        ret = subprocess.run([chmod_cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        print(ret)

    def get_all_hvigor_projects(self):
        cmd = "./get_app_projects.sh {} hvigor_project".format(self.xts_root)
        ret = subprocess.run([cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        projects = ret.stdout.decode().strip().split('\n')
        # print("projects={}".format(projects))
        return projects

    def get_all_gn_projects(self):
        cmd = "./get_app_projects.sh {} gn_project".format(self.xts_root)
        ret = subprocess.run([cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        projects = ret.stdout.decode().strip().split('\n')
        # print("projects={}".format(projects))
        return projects

    def get_all_bundle_json(self):
        cmd = "find {} -name bundle.json".format(self.code_root)
        ret = subprocess.run([cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        bundle_jsons = ret.stdout.decode().strip().split('\n')
        return bundle_jsons

    def get_indent(self, cfg_file):
        cmd = "./get_indent.sh {}".format(cfg_file)
        ret = subprocess.run([cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        indent = ret.stdout.decode().strip()
        return indent

    def is_dos_format(self, cfg_file):
        cmd = "./is_dos_format.sh {}".format(cfg_file)
        ret = subprocess.run([cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        is_dos = ret.stdout.decode().strip()
        return is_dos

    def get_component_syscaps(self, bundle_file):
        with open(bundle_file, 'r') as f:
            load_dict = json.load(f)
            if not load_dict.get("component"):
                return {}
            component_name = load_dict.get("component").get("name")
            syscaps = load_dict.get("component").get("syscap")
            # 删除赋值为false的syscap
            # 例如：SystemCapability.Communication.WiFi.AP.Extension = false
            if not syscaps:
                syscaps = []
            for i in syscaps:
                if re.search(" *= *false", i):
                    syscaps.remove(i)
            return {component_name: syscaps}

    def get_component_syscaps_forall(self):
        bundle_jsons = self.get_all_bundle_json()
        for i in bundle_jsons:
            component = self.get_component_syscaps(i)
            if len(component) == 0:
                continue
            self.components_syscaps.update(component)
        # print("self.components_syscaps={}".format(self.components_syscaps))

    # 获取hvigor工程的组件名
    def get_component_name_of_project(self, hvigor_project):
        gn_file = os.path.join(hvigor_project, "BUILD.gn")
        cmd = './get_component_name.sh {}'.format(gn_file)
        ret = subprocess.run([cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        return ret.stdout.decode().strip().split('\n')[0]

    def get_project_hap_directory(self, hvigor_project):
        cmd = "find {} -name module.json5 -o -name config.json | xargs dirname".format(hvigor_project)
        ret = subprocess.run([cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        project_hap_dirs = ret.stdout.decode().strip().split('\n')
        return project_hap_dirs

    def clear_device_type_in_config_json(self, cfg_file):
        sh_file = os.path.join(self.work_dir, "clear_config_json.sh")
        shell_cmd = "{} {}".format(sh_file, cfg_file)
        ret = subprocess.run([shell_cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        if ret.returncode:
            print(ret)

    def clear_device_type_in_module_json5(self, cfg_file):
        sh_file = os.path.join(self.work_dir, "clear_module_json5.sh")
        shell_cmd = "{} {}".format(sh_file, cfg_file)
        ret = subprocess.run([shell_cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        if ret.returncode:
            print(ret)

    def clear_devicetype_in_hap_cfg(self, hap_directory):
        if not self._clear_devicetype:
            return
        if os.path.exists(os.path.join(hap_directory, "config.json")):
            self.clear_device_type_in_config_json(os.path.join(hap_directory, "config.json"))
        elif os.path.exists(os.path.join(hap_directory, "module.json5")):
            self.clear_device_type_in_module_json5(os.path.join(hap_directory, "module.json5"))
        else:
            print("warning: Cannot find config in {}".format(hap_directory))

    def get_devicetype(self, hap_directory):
        cfg_file = os.path.join(hap_directory, "config.json")
        if os.path.exists(cfg_file):
            with open(cfg_file, 'r') as rf:
                load_dict = json.load(rf)
                return load_dict.get("module")["deviceType"]
        cfg_file = os.path.join(hap_directory, "module.json5")
        if os.path.exists(cfg_file):
            with open(cfg_file, 'r') as rf:
                load_dict = json5.load(rf)
                return load_dict.get("module")["deviceTypes"]
        return []

    def enbale_hap_syscap_gen_syscap_json(self, hap_directory, syscaps):
        syscap_json_file = os.path.join(hap_directory, "syscap.json")
        json_content = {"devices": {"general": [], "custom": [{"xts": []}]}}
        if not self._clear_devicetype:
            json_content.get("devices")["general"] = self.get_devicetype(hap_directory)
        if len(syscaps):
            json_content.get("devices").get("custom")[0]["xts"] = syscaps
        else:
            json_content.get("devices").get("custom")[0]["xts"] = ["SystemCapability.Startup.SystemInfo"]
        with open(syscap_json_file, "w") as wf:
            wf.write(json.dumps(json_content, indent=4, ensure_ascii=False))

    def enable_hap_syscap(self, hap_directory, syscaps):
        # 清空配置文件中device_type
        self.clear_devicetype_in_hap_cfg(hap_directory)
        # 添加syscap.json
        # syscap_json_file = os.path.join(hap_directory, "syscap.json")
        self.enbale_hap_syscap_gen_syscap_json(hap_directory, syscaps)

    def can_enable(self, syscaps):
        for syscap in syscaps:
            num = len(syscap.split('.'))
            if num == 2 or num == 5:
                return False
        return True

    def enable_project_syscap(self, hvigor_project):
        component_name = self.get_component_name_of_project(hvigor_project)
        # print("component_name=[{}]".format(component_name))
        if component_name not in self.components_syscaps:
            print("warning: part_name {} configured in {}/BUILD.gn is not exist".format(
                component_name, hvigor_project.replace("{}/".format(self.code_root), '')))
            return
        syscaps = self.components_syscaps.get(component_name)
        if not self.can_enable(syscaps):
            print("{} cannot enable syscap, because syscap format not support, syscap:{}".format(
                hvigor_project, syscaps))
            return
        if len(syscaps) == 0:
            print("warning: {} belong to {}, not config syscap".format(hvigor_project, component_name))
        # print ("hvigor_project={},syscaps={}".format(hvigor_project, syscaps))
        project_hap_dirs = self.get_project_hap_directory(hvigor_project)
        for hap_directory in project_hap_dirs:
            self.enable_hap_syscap(hap_directory, syscaps)
        # print(syscaps)

    def enable_project_syscap_forall(self):
        hvigor_projects = self.get_all_hvigor_projects()
        # print("hvigor_projects={}".format(hvigor_projects))
        for project in hvigor_projects:
            short_project = project.replace("{}/".format(self.xts_root), '')
            if short_project in self.exclude_project:
                continue
            self.enable_project_syscap(project)

    # 用于检查hvigor和非hvigor工程的part_name是否正确配置
    def check_part_name(self):
        hvigor_projects = self.get_all_hvigor_projects()
        gn_projects = self.get_all_gn_projects()
        hap_projects = []
        hap_projects.extend(hvigor_projects)
        hap_projects.extend(gn_projects)
        for project in hap_projects:
            project_short = project.replace('{}/'.format(self.xts_root), '')
            component_name = self.get_component_name_of_project(project)
            if component_name not in self.components_syscaps:
                print("warning: part_name {} configured in {}/BUILD.gn is not exist".format(
                    component_name, project.replace("{}/".format(self.code_root), '')))
                continue
            first_1_dir = project_short.split('/')[0]
            first_2_dir = "/".join(project_short.split('/')[0:2])

            if first_2_dir in self.dir_to_modules:
                if component_name in self.dir_to_modules.get(first_2_dir):
                    # print("Project {} check {} success".format(project_short, component_name))
                    continue
                else:
                    subsystem = self.subsystem_of_module.get(component_name)
                    print("Error: Project {} check {} failed, should belong to {}".format(project_short, component_name, subsystem))
            elif first_1_dir in self.dir_to_modules:
                if component_name in self.dir_to_modules.get(first_1_dir):
                    # print("Project {} check {} success".format(project_short, component_name))
                    continue
                else:
                    subsystem = self.subsystem_of_module.get(component_name)
                    print("Error: Project {} check {} failed, should belong to {}".format(project_short, component_name, subsystem))
            else:
                print("Error: Project {} cannot find from dir_to_modules")
            print("project={}, first_1_dir={}, first_2_dir={}, component_name={}".format(
                project_short, first_1_dir, first_2_dir, component_name))
            print("project={}, self.dir_to_modules[first_1_dir]={}, self.dir_to_modules[first_2_dir]".format(
                project_short, self.dir_to_modules.get(first_1_dir), self.dir_to_modules.get(first_2_dir)))


def main():
    '''
    python3 -B gen_syscap_json.py [clear]
    如果带了参数,将清空config.json中的devicetype
    '''
    args = sys.argv[1:]
    print(args)
    clear_devicetype = True if len(args) else False
    print("clear_devicetype={}".format(clear_devicetype))
    syscap = SystemCapability(clear_devicetype)
    syscap.prepare()
    syscap.get_component_syscaps_forall()
    syscap.enable_project_syscap_forall()

    # syscap.check_part_name()

    # 临时调试用
    # xts_root = "/home/f00829171/code/gitee/git/chris1766/xts_acts"
    # project = "ability/ability_runtime/abilitymultiinstance/amsabilitymultiinstanceappe"
    # syscap.enable_project_syscap(os.path.join(xts_root, project))


if __name__ == "__main__":
    sys.exit(main())
